﻿/*
  DISCLAIMER:
THIS CODE IS SAMPLE CODE. THESE SAMPLES ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND.
MICROSOFT FURTHER DISCLAIMS ALL IMPLIED WARRANTIES INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR OF FITNESS FOR
A PARTICULAR PURPOSE. THE ENTIRE RISK ARISING OUT OF THE USE OR PERFORMANCE OF THE SAMPLES REMAINS WITH YOU. IN NO EVENT SHALL
MICROSOFT OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE THE
SAMPLES, EVEN IF MICROSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION
OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
 * */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Xml;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace WebDAV_Test_Application
{
    class ClassWebDAV
    {
        private string _targetURL="";
        private ICredentials _credentials = null;
        private bool _bypassWebProxy = false;
        private ClassLogger _logger = null;

        public ClassWebDAV(string TargetURL, ICredentials Credential, bool BypassWebProxy, ClassLogger Logger)
        {
            // Initialise the class
            _targetURL = TargetURL;
            _credentials = Credential;
            _bypassWebProxy = BypassWebProxy;
            _logger = Logger;
        }

        public string TargetURL
        {
            get { return _targetURL; }
            set { _targetURL = value; }
        }

        public ICredentials Credentials
        {
            get { return _credentials; }
            set { _credentials = value; }
        }

        public bool BypassWebProxy
        {
            get { return _bypassWebProxy; }
            set { _bypassWebProxy = value; }
        }

        public string SendRequest(string Request, string Method, List<string[]> Headers=null, bool ReturnHeaders=true)
        {
            // Send the request and return the response
            
            if (String.IsNullOrEmpty(_targetURL)) return "Error occurred: no target server specified";
            if (String.IsNullOrEmpty(Method)) return "Error: no HTTP Method specified";

            string sResponse = "";
            HttpWebRequest oWebRequest = (HttpWebRequest)WebRequest.Create(_targetURL);
            if (_bypassWebProxy)
                oWebRequest.Proxy = GlobalProxySelection.GetEmptyWebProxy();
            oWebRequest.Credentials = _credentials;

            oWebRequest.ContentType = "text/xml";
            oWebRequest.Accept = "text/xml";
            oWebRequest.Method = Method;

            // Add any other headers provided
            if (Headers!=null)
            {
                foreach (string[] sHeader in Headers)
                {
                    if (!string.IsNullOrEmpty(sHeader[0]))
                    {
                        try
                        {
                            oWebRequest.Headers.Add(sHeader[0], sHeader[1]);
                        }
                        catch     { }
                    }
                    
                }
            }

            XmlDocument oWebDAVRequest = new XmlDocument();
            try
            {
                if (!string.IsNullOrEmpty(Request))
                    oWebDAVRequest.LoadXml(Request);
            }
            catch (Exception ex)
            {
                sResponse = "Request was invalid XML: " + ex.Message + "\n\r\n\r" + Request;
                return sResponse;
            }
            Stream stream = null;
            try
            {
                stream = oWebRequest.GetRequestStream();
            }
            catch (Exception ex)
            {
                // Failed to send request
                return "Error occurred: " + ex.Message + "\n\r\n\r";
            }
            if (!string.IsNullOrEmpty(Request))
                oWebDAVRequest.Save(stream);
            stream.Close();

            if (ReturnHeaders)
            {
                // If we are returning headers, we'll also log them
                string sRequestHeaders = "";
                foreach (string sHeader in oWebRequest.Headers.Keys)
                {
                    sRequestHeaders += sHeader + ": " + oWebRequest.Headers[sHeader].ToString() + Environment.NewLine;
                }
                Log(sRequestHeaders + Environment.NewLine + oWebDAVRequest.InnerXml, "Request");
            }
            else
                Log(oWebDAVRequest.InnerXml, "Request");

            IAsyncResult asyncResult = oWebRequest.BeginGetResponse(null, null);
            asyncResult.AsyncWaitHandle.WaitOne();

            WebResponse oWebResponse = null;
            try
            {
                oWebResponse = oWebRequest.EndGetResponse(asyncResult);
            }
            catch (Exception ex)
            {
                if (ex is WebException)
                {
                    WebException wex = ex as WebException;
                    sResponse = "Error occurred: " + wex.Message + "\n\r\n\r" + GetRequestError(wex);
                }
                else
                    sResponse = "Error occurred: " + ex.Message + "\n\r\n\r";
            }
            try
            {
                using (StreamReader oReader = new StreamReader(oWebResponse.GetResponseStream()))
                {
                    sResponse += oReader.ReadToEnd();
                }
            }
            catch { }

            string sHeaders = "";
            if (oWebResponse != null)
            {
                foreach (string sHeaderName in oWebResponse.Headers.Keys)
                {
                    sHeaders += sHeaderName + ": " + oWebResponse.Headers[sHeaderName] + Environment.NewLine;
                }
            }
            try
            {
                oWebResponse.Close();
            }
            catch { }

            if (ReturnHeaders)
                sResponse = sHeaders + Environment.NewLine + sResponse;
            Log(sResponse, "Response");
            return sResponse;
        }

        private string GetRequestError(WebException WebEx)
        {
            try
            {
                string sError = "";
                using (StreamReader oReader = new StreamReader(WebEx.Response.GetResponseStream()))
                {
                    sError += oReader.ReadToEnd();
                }
                return sError;
            }
            catch
            {
                return "No response was returned.";
            }
        }

        private void Log(string Details, string Description="")
        {
            try
            {
                if (_logger == null) return;
                _logger.Log(Details, Description);
            }
            catch { }
        }
    }
}
